home *** CD-ROM | disk | FTP | other *** search
- /* There are only two functions in this mailbox code that depend on the
- * underlying protocol, namely mbx_getname() and dochat(). All the other
- * functions can hopefully be used without modification on other stream
- * oriented protocols than AX.25 or NET/ROM.
- *
- * SM0RGV 890506, most work done previously by W9NK
- *
- *** Changed 900114 by KA9Q to use newline mapping features in stream socket
- * interface code; everything here uses C eol convention (\n)
- *
- * Numerous new commands and other changes by SM0RGV, 900120
- */
- #include <stdio.h>
- #include <time.h>
- #include <ctype.h>
- #ifdef UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
- #include <io.h>
- #include "global.h"
- #include "config.h"
- #include "bm.h"
- #include "timer.h"
- #include "mailbox.h"
- #include "cmdparse.h"
- #include "proc.h"
- #include "socket.h"
- #include "usock.h"
- #include "session.h"
- #include "ax25.h"
- #include "smtp.h"
- #include "dirutil.h"
- #include "telnet.h"
- #include "ftp.h"
- #include "ftpserv.h"
- #include "netrom.h"
- #include "commands.h"
- #include "netuser.h"
- #include "files.h"
-
- #define MAX_MBXERR 5 /* a try to stop endless "Huh?" or "Error ?" */
- // #define RMNCSYS 17034
- extern char RouteHeader[];
- static int Stelnet = -1;
- /* extern int dumproute __ARGS((struct route *rp,char *p)); */
-
- #ifdef NETROM
- #define STACKSIZE 3072
- static int Nrsocket = -1;
- #else
- #define STACKSIZE 2048
- #endif
-
- extern char No[];
-
- struct mbx *Mbox[NUMMBX];
- static int MAttended = 1; /* default to attended mode */
- static int ThirdParty = 1; /* default to thirdparty mail allowed */
- unsigned Maxlet = BM_NLET;
- #ifdef XXX
- unsigned Tiptimeout = 180; /* Default tip inactivity timeout (seconds) */
- #endif
- int Mbmore = 0;
- int bbsUsers;
-
- static int Areawait = 0;
-
- char Banner[] = "[WNOS-H$]\n";
- static char Noperm[] = "Permission denied\n";
-
- static char *MBlogname = NULLCHAR;
- static char *MHostname = NULLCHAR;
- static char MBHostname[30] = "\0";
- static char MMotd[256] = "\0";
- static char Mbbanner[] = "'s TCP/IP system.";
- static char number[7];
- static char Loginbanner[] = "WNOS (%s)\n";
- static char Howtoend[] = "Terminate with /EX or ^Z in first column (^A aborts)\n";
- static char Aborted[] = "*** aborted\n";
- static char mbnrid[20] = "\0";
- #if (!defined(AX25) || defined(NETROM))
- static char Noserv[] = "Service unavailable\n";
- #endif
- #ifdef XXX
- static int dombiproute __ARGS((int argc,char *argv[],void *p));
- #endif
- static int doattend __ARGS((int argc,char *argv[],void *p));
- static int dofinfo __ARGS((int argc,char *argv[],void *p));
- static int dofnic __ARGS((int argc,char *argv[],void *p));
- static int domblog __ARGS((int argc,char *argv[],void *p));
- static int domaxmsg __ARGS((int argc,char *argv[],void *p));
- static int dombmotd __ARGS((int argc,char *argv[],void *p));
- static int dombmore __ARGS((int argc,char *argv[],void *p));
- static int dosend __ARGS((int argc,char *argv[],void *p));
- static int dosid __ARGS((int argc,char *argv[],void *p));
- #ifdef XXX
- static int dotimeout __ARGS((int argc,char *argv[],void *p));
- #endif
- static int dombescape __ARGS((int argc,char *argv[],void *p));
- #ifdef AX25
- static int dombheard __ARGS((int argc,char *argv[],void *p));
- #endif
- static int dodownload __ARGS((int argc,char *argv[],void *p));
- static int dombupload __ARGS((int argc,char *argv[],void *p));
- static int dowhat __ARGS((int argc,char *argv[],void *p));
- static int dosysop __ARGS((int argc,char *argv[],void *p));
- static int dostars __ARGS((int argc,char *argv[],void *p));
- static int doarea __ARGS((int argc,char *argv[],void *p));
- static int dombhelp __ARGS((int argc,char *argv[],void *p));
- static int dogateway __ARGS((int argc,char *argv[],void *p));
- static int dombhostname __ARGS((int argc,char *argv[],void *p));
- static int dombtelnet __ARGS((int argc,char *argv[],void *p));
- #ifdef CONVERS
- static int dombconvers __ARGS((int argc,char *argv[],void *p));
- #endif
- static int dombfinger __ARGS((int argc,char *argv[],void *p));
- #ifdef AX25
- static int dombroute __ARGS((int argc,char *argv[],void *p));
- #endif
- static int dombstat __ARGS((int argc,char *argv[],void *p));
- static int dombuser __ARGS((int argc,char *argv[],void *p));
- #ifdef NETROM
- static int dombnrconnect __ARGS((int argc,char *argv[],void *p));
- static int dombnodes __ARGS((int argc,char *argv[],void *p));
- #endif
- static void gw_alarm __ARGS((void *p));
- static int near mbx_getname __ARGS((struct mbx *m));
- static int near mbxrecvline __ARGS((int s,char *buf,int len,int escape));
- static int near gw_connect __ARGS((struct mbx *m,int s,char *fsocket,int len));
- static void gw_input __ARGS((int s,void *notused,void *p));
- static void gw_superv __ARGS((int null,void *proc,void *p));
- static int near mbx_to __ARGS((int argc,char *argv[],void *p));
- static int near mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra));
- static int near msgidcheck __ARGS((char *string));
- static int near uuencode __ARGS((FILE *infile,int s,char *infilename));
- static int thirdparty __ARGS((struct mbx *m));
- int setuns __ARGS((unsigned *var,char *label,int argc,char *argv[]));
-
- static struct cmds near Mbcmds[] = { /* TEST */
- "", doreadnext, 0, 0, NULLCHAR,
- "area", doarea, 0, 0, NULLCHAR,
- "bye ", domboxbye, 0, 0, NULLCHAR,
- "chat", dogateway, 0, 0, NULLCHAR,
- "connect", dogateway, 0, 0, NULLCHAR,
- #ifdef CONVERS
- "convers", dombconvers, 0, 0, NULLCHAR,
- #endif
- "download", dodownload, 0, 2, "d[u] file",
- "escape", dombescape, 0, 0, NULLCHAR,
- "finger", dombfinger, 0, 0, NULLCHAR,
- "help", dombhelp, 0, 0, NULLCHAR,
- "info", dombhelp, 0, 0, NULLCHAR,
- #ifdef XXX
- "iproute", dombiproute, 0, 0, NULLCHAR,
- #endif
- "kill", dodelmsg, 0, 2, "k #",
- "list", dolistnotes, 0, 0, NULLCHAR,
- #ifdef AX25
- "mheard", dombheard, 0, 0, NULLCHAR,
- #endif
- #ifdef NETROM
- "nodes", dombnodes, 0, 0, NULLCHAR,
- "nconnect", dombnrconnect, 0, 2, "nc call|node",
- #endif
- #ifdef AX25
- "path", dombroute, 0, 0, NULLCHAR,
- #endif
- "quit", domboxbye, 0, 0, NULLCHAR,
- "read", doreadmsg, 0, 2, "r #",
- "send", dosend, 0, 0, NULLCHAR,
- "telnet", dombtelnet, 0, 2, "t host",
- "user", dombuser, 0, 0, NULLCHAR,
- "upload", dombupload, 0, 2, "u file",
- "what", dowhat, 0, 0, NULLCHAR,
- "? ", dombhelp, 0, 0, NULLCHAR,
- /* cmds down here are not displayed by the "?" cmd */
- "os", dombstat, 0, 0, NULLCHAR,
- "[", dosid, 0, 0, NULLCHAR,
- #ifdef AX25
- "f>", dorevfwd, 0, 0, NULLCHAR,
- #endif
- "@", dosysop, 0, 0, NULLCHAR,
- "v", doreadmsg, 0, 2, "v #",
- "xr", dombhostname, 0, 0, NULLCHAR,
- "***", dostars, 0, 0, NULLCHAR,
- NULLCHAR, NULLFP, 0, 0, "\n*** invalid command\n",
- };
-
- #ifdef AX25
- int
- ax25start(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s, type;
-
- if (Axi_sock != -1)
- return 0;
-
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"AX25 listener");
- Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
- /* bind() is done automatically */
- listen(Axi_sock,1);
-
- for(;;){
- if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
- break; /* Service is shutting down */
- type = AX25TNC;
- /* Eat the line that triggered the connection
- * and then start the mailbox
- */
- sockmode(s,SOCK_ASCII); /* To make recvline work */
- recvline(s,NULLCHAR,80);
- newproc("mbox",STACKSIZE,mbx_incom,s,(void *)type,NULL,0);
- }
- return 0;
- }
-
- int
- ax250(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Axi_sock);
- Axi_sock = -1;
- return 0;
- }
- #endif
-
- /* Start up Telnet server */
- int
- telnet1(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct sockaddr_in lsocket;
- int s;
-
- if(Stelnet != -1){
- return 0;
- }
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"Telnet listener");
-
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- lsocket.sin_port = (argc < 2) ? IPPORT_TELNET : atoi(argv[1]);
-
- Stelnet = socket(AF_INET,SOCK_STREAM,0);
- bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
-
- listen(Stelnet,1);
-
- for(;;){
- if((s = accept(Stelnet,NULLCHAR,NULLINT)) == -1)
- break; /* Service is shutting down */
- if(availmem() < Memthresh){
- usputs(s,Nospace);
- shutdown(s,1);
- } else {
- /* Spawn a server */
- int type = TELNET;
- newproc("mbox",STACKSIZE,mbx_incom,s,(void *)type,NULL,0);
- }
- }
- return 0;
- }
-
- /* Stop telnet server */
- int
- telnet0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Stelnet);
- Stelnet = -1;
- return 0;
- }
-
- #ifdef NETROM
- int
- nr4start(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s, type;
-
- if (Nrsocket != -1)
- return 0;
-
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"NETROM listener");
- Nrsocket = socket(AF_NETROM,SOCK_SEQPACKET,0);
- /* bind() is done automatically */
-
- listen(Nrsocket,1);
-
- for(;;){
- if((s = accept(Nrsocket,NULLCHAR,NULLINT)) == -1)
- break; /* Service is shutting down */
- type = NRSESSION;
- newproc("mbox",STACKSIZE,mbx_incom,s,(void *)type,NULL,0);
- }
- return 0;
- }
-
- int
- nr40(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Nrsocket);
- Nrsocket = -1;
- return 0;
- }
- #endif
-
- #if defined(ANSIPROTO)
- static void near
- logmb(int s,char *fmt, ...)
- {
- va_list ap;
- char *cp;
- long t;
- int i;
- struct sockaddr fsocket;
- FILE *MBLogfp;
-
- if(MBlogname == NULLCHAR
- || (MBLogfp = open_file(MBlogname,APPEND_TEXT,0,1)) == NULLFILE)
- return;
-
- time(&t);
- cp = ctime(&t);
- rip(cp);
- i = SOCKSIZE;
- fprintf(MBLogfp,"%s",cp);
- if(getpeername(s,(char *)&fsocket,&i) != -1)
- fprintf(MBLogfp," %s",psocket(&fsocket));
-
- fprintf(MBLogfp," - MBOX ");
- va_start(ap,fmt);
- vfprintf(MBLogfp,fmt,ap);
- va_end(ap);
- fprintf(MBLogfp,"\n");
- fclose(MBLogfp);
- }
- #else
- /*VARARGS2*/
- static void near
- logmb(s,fmt,arg1,arg2,arg3,arg4,arg5)
- int s;
- char *fmt;
- int arg1,arg2,arg3,arg4,arg5;
- {
- char *cp;
- long t;
- int i;
- struct sockaddr fsocket;
- FILE *MBLogfp;
-
- if(MBlogname == NULLCHAR
- || (MBLogfp = open_file(MBlogname,APPEND_TEXT,0,1)) == NULLFILE)
- return;
-
- time(&t);
- cp = ctime(&t);
- rip(cp);
- i = SOCKSIZE;
- fprintf(MBLogfp,"%s",cp);
- if(getpeername(s,(char *)&fsocket,&i) != -1)
- fprintf(MBLogfp," %s",psocket(&fsocket));
-
- fprintf(MBLogfp," - ");
- fprintf(MBLogfp,fmt,arg1,arg2,arg3,arg4,arg5);
- fprintf(MBLogfp,"\n");
- fclose(MBLogfp);
- }
- #endif
-
- int
- dombox(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- /* mbox subcommand table */
- struct cmds Mbtab[] = {
- "attend", doattend, 0, 0, NULLCHAR,
- #ifdef AX25
- "finfo", dofinfo, 0, 0, NULLCHAR,
- "fkick", dombkick, 0, 0, NULLCHAR,
- "fnic", dofnic, 0, 0, NULLCHAR,
- "ftimer", dombtimer, 0, 0, NULLCHAR,
- #endif
- "log", domblog, 0, 0, NULLCHAR,
- "maxmsg", domaxmsg, 0, 0, NULLCHAR,
- "motd", dombmotd, 0, 0, NULLCHAR,
- "more", dombmore, 0, 0, NULLCHAR,
- "remote", dombhostname, 0, 0, NULLCHAR,
- "status", domboxdisplay, 0, 0, NULLCHAR,
- #ifdef XXX
- "tiptimeout", dotimeout, 0, 0, NULLCHAR,
- #endif
- "user", dombuser, 0, 0, NULLCHAR,
- NULLCHAR,
- };
- return subcmd(Mbtab,argc,argv,p);
- }
-
- static int
- doattend(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&MAttended,"Mbox attended",argc,argv);
- }
-
- /* Set the Info field of R: header (eg forward info "[Bath, Avon - WNOS3]") */
- static int
- dofinfo( argc, argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- extern char *FInfo;
-
- if(argc < 2 && FInfo != NULLCHAR)
- tprintf("FBBS Info: %s\n", FInfo);
- else {
- if (FInfo != NULLCHAR)
- xfree(FInfo);
- FInfo = mxallocw(25);
- sprintf(FInfo,"%.24s",argv[1]);
- }
- return 0;
- }
-
- /* Set Nic field of R: header (eg forward nic ".GB7IMB.#41.GBR.EU" */
- static int
- dofnic(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- extern char *FNic;
-
- if(argc < 2 && FNic != NULLCHAR)
- tprintf("FNIC id: %s\n", FNic);
- else {
- if(FNic != NULLCHAR)
- xfree(FNic);
- FNic = mxallocw(25);
- sprintf(FNic,"%.24s",argv[1]);
- }
- return 0;
- }
-
- static int
- domblog(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2){
- if(MBlogname != NULLCHAR)
- tprintf("MBLog to %s\n",MBlogname);
- else
- tputs("MBLog off\n");
- } else {
- if(MBlogname != NULLCHAR) {
- xfree(MBlogname);
- MBlogname = NULLCHAR;
- }
- if(strcmp(argv[1],"off") != 0)
- MBlogname = strxdup(Mboxlog);
- }
- return 0;
- }
-
- static int
- domaxmsg(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setuns(&Maxlet,"Max msgs per area",argc,argv);
- }
-
- #ifdef XXX
- static int
- dotimeout(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setuns(&Tiptimeout,"Tip conn timeout",argc,argv);
- }
- #endif
-
- static int
- dombmore(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Mbmore,"Mbox more",argc,argv);
- }
-
- static int
- dombmotd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int i;
-
- if(argc < 2 && MMotd[0] != '\0')
- tputs(MMotd);
- else {
- MMotd[0] = '\0';
-
- for(i = 1; i < argc; i++) {
- strcat(MMotd,argv[i]);
- if(strlen(MMotd) > 220)
- break;
- strcat(MMotd," ");
- }
- if(strlen(MMotd) > 2)
- strcat(MMotd,"\n\0");
- else
- MMotd[0] = '\0';
- }
- return 0;
- }
-
- static int
- dombhostname(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *) p;
-
- if(*argv[0] == 'x')
- if(!(m->privs & SYSOP_CMD))
- return -3;
-
- if(argc < 2 && MHostname != NULLCHAR) {
- tprintf("%s\n",MHostname);
- } else {
- if(MHostname != NULLCHAR)
- xfree(MHostname);
- MHostname = strxdup(argv[1]);
- }
- return 0;
- }
-
- static int
- domboxdisplay(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int i, j, len;
- struct mbx *m;
- char fsocket[MAXSOCKSIZE], *states[] =
- {"LOGIN","CMD","SUBJ","DATA","REVFWD","TRYING","FORWARD","CONVERS"};
-
- tputs("User State S# Where\n");
- for (i = 0; i < NUMMBX; i++) {
- if((m = Mbox[i]) != NULLMBX) {
- len = MAXSOCKSIZE;
- j = getpeername(m->user,fsocket,&len);
- tprintf("%-11s%-9s%-4u%s\n",
- m->name,
- states[m->state],
- m->user,
- (j != -1) ? psocket(fsocket) : "");
- }
- }
- return 0;
- }
-
- struct mbx *
- newmbx()
- {
- int i;
- struct mbx *m;
-
- for(i = 0; i < NUMMBX; i++){
- if(Mbox[i] == NULLMBX){
- m = Mbox[i] = (struct mbx *)mxallocw(sizeof(struct mbx));
- bbsUsers++;
- m->mbnum = i;
- return m;
- }
- }
- /* If we get here, there are no free mailbox sessions */
- return NULLMBX;
- }
-
- /* Incoming mailbox session */
- static void
- mbx_incom(s,t,p)
- int s;
- void *t;
- void *p;
- {
- struct mbx *m;
- struct usock *up;
- int rval;
- char *cp, *cp1, *buf[3], buf2[77], buf3[77];
- FILE *fp;
-
- sockmode(s,SOCK_ASCII);
- sockowner(s,Curproc); /* We own it now */
- close_s(Curproc->output);
- close_s(Curproc->input);
- Curproc->output = Curproc->input = s;
-
- if((m = newmbx()) == NULLMBX){
- usputs(s,Nosess);
- return;
- }
- setflush(s,-1);
-
- m->user = s;
- m->escape = 24; /* default escape character is Ctrl-X */
- m->type = (int) t;
-
- /* get the name of the remote station */
- if(mbx_getname(m) == -1) {
- exitbbs(m);
- return;
- }
- #ifdef NETROM
- if(Nrifaces[0].alias != NULLCHAR) {
- cp = strxdup(Nrifaces[0].alias);
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(mbnrid,"%s:%s> ",cp,pax25(m->line,Nrifaces[0].iface->hwaddr));
- xfree(cp);
- } else
- #endif
- mbnrid[0] = '\0';
-
- sprintf(MBHostname,"%.28s",Hostname);
- if((cp = strchr(MBHostname,'.')) != NULLCHAR)
- *cp = '\0';
- strupr(MBHostname);
- m->state = MBX_CMD; /* start in command state */
-
- // DL8YQ /* Now say hi */
- cp='\0';
- cp=strxdup(m->name);
- if((fp = fopen(Bbsfile,READ_TEXT)) != NULLFILE){
-
- while (fgets(buf2,LINELEN,fp),!feof(fp)){
- if (buf2[0] == '#')
- continue;
-
- buf2[strlen(buf2)-1]=0;
- if(strcmp(buf2,cp) == 0){
- usprintf(m->user,"%s %s\n",Hostname,Mbbanner);
- usflush(m->user);
- pause(3000L);
- usprintf(m->user,Banner);
- usflush(m->user);
- pause(4000L);
- break;
-
- }
- }
- }
- fclose(fp);
- strcpy(buf3,buf2);
- if(strcmp(buf2,cp) != 0){
- usprintf(m->user,"Welcome %s at %s %s Currently %d user%s\n",cp,Hostname,Mbbanner,bbsUsers,bbsUsers == 1 ? "" : "s");
- sprintf(buf2,"%s/host.hlp",Helpdir);
- if((fp = fopen(buf2,READ_TEXT)) != NULLFILE) {
- usputs(m->user,"\n");
- sendfile(fp,m->user,ASCII_TYPE,0);
- fclose(fp);
- } else
- usputs(m->user,"Type '?' for help.\n");
-
- if(MMotd != NULLCHAR)
- usprintf(m->user,"%s\n",MMotd);
- usprintf(m->user,"Login at %s\n",ptime(&currtime));
- usprintf(m->user,"Prog. runtime: %s (%lu Byte coreleft)\n\n",tformat(secclock()),availmem());
- }
- /* Enable our local message area */
- buf[1] = m->name;
-
- doarea(2,buf,m);
-
- cp1 = strxdup(m->name);
- strupr(cp1);
- // >muss hinter dem %s
- if (strcmp(buf3,cp) == 0){
- usprintf(m->user,">\r");
- xfree(cp);
- }
- else
- usprintf(m->user,"(%s) %s de %s>\n",m->narea,cp1,MBHostname);
- while(mbxrecvline(s,m->line,MBXLINE,-1) != EOF){
- if((rval = mbx_parse(m)) == -2)
- break;
- if(rval == 1)
- usputs(m->user,"Bad syntax\n");
- if(!(m->sid & MBX_SID) && isnewprivmail(m) > 0L)
- usputs(m->user,"You have new mail\n");
- scanmail(m);
- if(m->sid & MBX_SID)
- usputs(m->user,">\n");
- else
- usprintf(m->user,"(%s) %s de %s>",m->narea,cp1,MBHostname);
-
- m->state = MBX_CMD;
- }
- xfree(cp1);
- exitbbs(m);
- /* nasty hack! we may have screwed up reference count */
- /* by invoking newproc("smtp_send",....); Fudge it! */
- if((up = itop(Curproc->output)) != NULLUSOCK)
- up->refcnt = 1;
- close_s(Curproc->output);
- return;
- }
-
- void
- exitbbs(m)
- struct mbx *m;
- {
- closenotes(m);
- xfree(m->to);
- xfree(m->origto);
- xfree(m->tofrom);
- xfree(m->tomsgid);
- if(m->tfile != NULLFILE)
- fclose(m->tfile);
- xfree(m->path);
- if(m->startmsg != NULLCHAR)
- xfree(m->startmsg);
- xfree((char *)m->mbox);
- /* close_s(m->user);
- m->user = -1; */
- Mbox[m->mbnum] = NULLMBX;
- xfree((char *)m);
- smtptick(NULL);
- bbsUsers--;
- }
-
- /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
- * They have to be treated specially since cmdparse() wants a space between
- * the actual command and its arguments.
- * "SP FOO" is converted to "s foo" and the second command letter is saved
- * in m->stype. Longer commands like "SEND" are unaffected, except for
- * commands starting with "[", i.e. the SID, since we don't know what it will
- * look like.
- */
- static char twocmds[] = "slrd["; /* S,L,R,D are two-letter commands */
-
- int
- mbx_parse(m)
- struct mbx *m;
- {
- int i;
- char *cp, *newargv[2];
-
- /* Translate entire buffer to lower case */
- for (cp = m->line; *cp != '\0'; ++cp)
- if(isupper(*cp))
- *cp = tolower(*cp);
- /* Skip any spaces at the begining */
- for(cp = m->line;isspace(*cp);++cp) ;
-
- m->stype = ' ';
-
- if(*cp != '\0' && *(cp+1) != '\0')
- for(i=0; i<strlen(twocmds); ++i){
- if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
- || *cp == '[')){
- if(islower(*(++cp)))
- m->stype = toupper(*cp); /* Save the second character */
- else
- m->stype = *cp;
- *cp = ' ';
- break;
- }
- }
-
- /* See if the input line consists solely of digits */
- cp = m->line;
- for(cp = m->line;isspace(*cp);++cp) ;
- newargv[1] = cp;
- for(;*cp != '\0' && isdigit(*cp);++cp) ;
- if(*cp == '\0' && strlen(newargv[1]) > 0) {
- newargv[0] = "read";
- return doreadmsg(2,newargv,(void *)m);
- } else {
- i = cmdparse(Mbcmds,m->line,(void *)m);
- switch(i) {
- case -3:
- tputs(Noperm);
- return 0;
- case -2:
- return -2;
- case -1:
- return (m->err_cnt++ >= MAX_MBXERR) ? -2 : -1;
- default:
- m->err_cnt = 0;
- return i;
- }
- }
- }
-
- static int near
- mbx_getname(m)
- struct mbx *m;
- {
- union sp sp;
- char *cp, tmp[MAXSOCKSIZE], buf[MBXLINE];
- int anony, oldmode, len = MAXSOCKSIZE;
-
- sp.p = tmp;
- sp.sa->sa_family = AF_LOCAL; /* default to AF_LOCAL */
- getpeername(m->user,tmp,&len);
- m->path = mxallocw(MBXLINE);
- m->family = sp.sa->sa_family;
-
- /* This is one of the two parts of the mbox code that depends on the
- * underlying protocol. We have to figure out the name of the
- * calling station. This is only practical when AX.25 or NET/ROM is
- * used. Telnet users have to identify themselves by a login procedure.
- */
- switch(sp.sa->sa_family){
- #ifdef AX25
- case AF_NETROM:
- case AF_AX25:
- /* NETROM and AX25 socket address structures are "compatible" */
- addrcp(m->nodename,sp.ax->ax25_addr);
- m->nodename[ALEN] ^= 0x1e;
- pax25(m->name,sp.ax->ax25_addr);
- log(m->user,"MBOX open");
- if((cp = strchr(m->name,'-')) != NULLCHAR)
- *cp = '\0';
-
- /* SMTP wants the name to be in lower case */
- strlwr(m->name);
-
- /* Try to find the privileges of this user from the userfile */
- anony = 1;
- if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony)) == -1) {
- if((m->privs = userlogin("bbs",buf,&m->path,MBXLINE,&anony)) == -1) {
- m->privs = 0;
- xfree(m->path);
- m->path = NULLCHAR;
- }
- }
- return (m->privs & EXCLUDED_CMD) ? -1 : 0;
- #endif
- case AF_LOCAL:
- case AF_INET:
- m->state = MBX_LOGIN;
- usprintf(m->user,Loginbanner,Hostname);
- for(;;){
- usputs(m->user,"Login (Call): ");
- usflush(m->user);
- if(mbxrecvline(m->user,buf,MBXLINE,-1) == EOF)
- return -1;
- if(*buf == '\0')
- continue;
-
- cp = buf;
- while(isspace(*cp)) cp++;
- sprintf(m->name,"%.19s",cp);
-
- #ifdef AX25
- if(setcall(m->nodename,m->name) == -1)
- addrcp(m->nodename,Mycall);
-
- m->nodename[ALEN] ^= 0x1e;
- #else
- m->nodename[0] = '\0';
- #endif
- usprintf(m->user,"Password: %c%c%c",IAC,WILL,TN_ECHO);
- usflush(m->user);
-
- /* SMTP wants the name to be in lower case */
- strlwr(m->name);
-
- oldmode = sockmode(m->user,SOCK_BINARY);
- if(mbxrecvline(m->user,buf,MBXLINE,-1) == EOF)
- return -1;
- usprintf(m->user,"%c%c%c",IAC,WONT,TN_ECHO);
- sockmode(m->user,oldmode);
- usputs(m->user,"\n");
- usflush(m->user);
- /* This is needed if the password was send before the
- * telnet no-echo options were receied. We neeed to
- * flush the eold sequence from the input buffers, sigh
- */
- if(socklen(m->user,0)) /* discard any remaining input */
- recv_mbuf(m->user,NULL,0,NULLCHAR,0);
- m->security = 0;
- anony = 0;
- if((m->privs = userlogin(m->name,buf,&m->path,MBXLINE,&anony)) == -1) {
- anony = 1;
- if((m->privs = userlogin("bbs",buf,&m->path,MBXLINE,&anony)) == -1) {
- m->privs = 0;
- xfree(m->path);
- m->path = NULLCHAR;
- }
- }
- log(m->user,"MBOX open %s %s",m->name,anony ? buf : "");
-
- m->security = anony;
- return (m->privs & EXCLUDED_CMD) ? -1 : 0;
- }
- }
- return -1;
- }
-
- /* This works like recvline(), but telnet options are answered and the
- * terminating newline character is not put into the buffer. If the
- * incoming character equals the value of escape, any queued input is
- * flushed and -2 returned.
- */
- static int near
- mbxrecvline(s,buf,len,escape)
- int s;
- char *buf;
- int len;
- int escape;
- {
- int c, cnt = 0, opt;
-
- if(buf == NULLCHAR)
- return 0;
-
- usflush(s);
- while((c = recvchar(s)) != EOF){
- if(c == IAC){ /* Telnet command escape */
- if((c = recvchar(s)) == EOF)
- break;
- if(c > 250 && c < 255 && (opt = recvchar(s)) != EOF){
- #ifdef foo
- switch(c){
- case WILL:
- usprintf(s,"%c%c%c",IAC,DONT,opt);
- break;
- case WONT:
- usprintf(s,"%c%c%c",IAC,DONT,opt);
- break;
- case DO:
- usprintf(s,"%c%c%c",IAC,WONT,opt);
- break;
- case DONT:
- usprintf(s,"%c%c%c",IAC,WONT,opt);
- }
- #endif
- /* to be fixed usflush(Curproc->output);*/
- continue;
- }
- if(c != IAC && opt == EOF)
- break;
- }
- /* ordinary character */
- if(c == '\r' || c == '\n')
- break;
- if(c == escape){
- if(socklen(s,0)) /* discard any remaining input */
- recv_mbuf(s,NULL,0,NULLCHAR,0);
- cnt = -2;
- break;
- }
- *buf++ = c;
- ++cnt;
- if(cnt == len - 1)
- break;
- }
- if(c == EOF && cnt == 0)
- return -1;
- *buf = '\0';
- return cnt;
- }
-
- int
- domboxbye(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *) p;
-
- /* Now say goodbye */
- usputs(m->user,"73!\n");
- usflush(Curproc->output);
- log(m->user,"MBOX close");
- return -2; /* signal that exitbbs() should be called */
- }
-
- static int
- dombhelp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[77];
- int i;
- FILE *fp;
- struct mbx *m = (struct mbx *) p;
-
- if(*argv[0] == '?') {
- struct cmds *cmdp;
-
- usputs(m->user,"\nAvailable commands:\n");
-
- for(i = 0, cmdp = Mbcmds; cmdp->name != NULLCHAR; cmdp++)
- if(strlen(cmdp->name) > 3) {
- usprintf(m->user,"%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
- i = (i + 1) % 5;
- }
- if(i)
- usputs(m->user,"\n");
- return 0;
- }
- buf[0] = '\0';
- if(argc > 1) {
- for(i = 0; Mbcmds[i].name != NULLCHAR; ++i)
- if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
- sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
- break;
- }
- } else
- sprintf(buf,"%s/%s.hlp",Helpdir,(*argv[0] == 'i') ? "info" : "help");
-
- if((fp = fopen(buf,READ_TEXT)) == NULLFILE)
- usprintf(m->user,"No %s available\n",(*argv[0] == 'i') ? "info" : "help");
- else {
- usprintf(m->user,"%s%s\n",
- (m->family == AF_NETROM) ? mbnrid : "",
- (*argv[0] == 'i') ? "Info:" : "");
- sendfile(fp,m->user,ASCII_TYPE,0);
- usputs(m->user,"\n");
- fclose(fp);
- }
- return 0;
- }
-
- /* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
- int
- dothirdparty(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&ThirdParty,"Third-Party Mail",argc,argv);
- }
-
- static int
- dosend(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int cccnt = 0, fail = 0;
- char *host, *cp, fullfrom[MBXLINE], sigwork[LINELEN], *rhdr = NULLCHAR;
- struct list *ap, *cclist = NULLLIST;
- FILE *fp;
-
- struct mbx *m = (struct mbx *)p;
-
- if(m->security == 1)
- return 0;
- if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m) == -1){
- usputs(m->user,(m->sid & MBX_SID) ? No :
- "Syntax error:\n"
- " S[F] name [@ host] [< from_addr] [$bulletin_id]\n"
- " SR [number]\n");
- return 0;
- }
- if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
- usprintf(m->user,"%sAlready have %s\n",
- (m->sid & MBX_SID) ? "NO - ":"",m->tomsgid);
- return 0;
- }
- if(m->stype == 'R' && !(m->sid & MBX_SID) &&
- mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
- return 0;
- if((cp = rewrite_address(m->to)) != NULLCHAR)
- if(strcmp(m->to,cp) != 0){
- m->origto = m->to;
- m->to = cp;
- } else
- xfree(cp);
-
- if(!ThirdParty && !(m->privs & SYSOP_CMD))
- if(thirdparty(m) == 0){
- usputs(m->user,(m->sid & MBX_SID) ? No : Noperm);
- return 0;
- }
-
- if((m->origto != NULLCHAR || m->stype == 'R') && !(m->sid & MBX_SID))
- usprintf(m->user,"To: %s\n", m->to);
- if(validate_address(m->to) == 0){
- usputs(m->user,(m->sid & MBX_SID) ? "NO\n" : "Bad user or host name\n");
- xfree(rhdr);
- del_list(cclist);
- /* We don't free any more buffers here. They are freed upon
- * the next kall to mbx_to() or to domboxbye()
- */
- return 0;
- }
- /* Display the Cc: line (during SR command) */
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- if(cccnt == 0){
- usputs(m->user,Hdrs[CC]);
- cccnt = 4;
- }
- else {
- usputs(m->user,", ");
- cccnt += 2;
- }
- if(cccnt + strlen(ap->val) > 80 - 3) {
- usputs(m->user,"\n ");
- cccnt = 4;
- }
- usputs(m->user,ap->val);
- cccnt += strlen(ap->val);
- }
- if(cccnt)
- usputs(m->user,"\n");
- m->state = MBX_SUBJ;
- if(m->stype != 'R' || (m->sid & MBX_SID) != 0) {
- usputs(m->user,(m->sid & MBX_SID) ? "OK\n" : " Subject: ");
- if(mbxrecvline(m->user,m->line,MBXLINE,-1) == -1)
- return 0;
- }
- else /* Replying to a message */
- usprintf(m->user," Subject: %s\n",m->line);
- if(mbx_data(m,cclist,rhdr) == -1){
- xfree(rhdr);
- del_list(cclist);
- usputs(m->user,(m->sid & MBX_SID) ? "*** NO\n": "Can't create mailfile\n");
- return 0;
- }
- xfree(rhdr);
- m->state = MBX_DATA;
- if(!(m->sid & MBX_SID) && m->stype != 'F')
- usprintf(m->user,"Enter message. %s",Howtoend);
-
- if(m->stype != 'F' || (m->sid & MBX_SID)) {
- while(mbxrecvline(m->user,m->line,MBXLINE,-1) != -1){
- if(m->line[0] == 0x01){ /* CTRL-A */
- fclose(m->tfile);
- usputs(m->user,Aborted);
- del_list(cclist);
- return 0;
- }
- if(m->line[0] != CTLZ
- && stricmp(m->line,"/ex")
- && stricmp(m->line,"***end")
- && stricmp(m->line,"."))
- fprintf(m->tfile,"%s\n",m->line);
- else {
- if(!(m->sid & MBX_SID))
- usputs(m->user,"Message saved\n");
- break; /* all done */
- }
- }
- } else {
- fputs("----- Forwarded message -----\n\n",m->tfile);
- msgtofile(m,m->current,m->tfile,0);
- fputs("----- End of forwarded message -----\n",m->tfile);
- }
-
- /* Insert customised signature if one is found */
- if(!(m->sid & MBX_SID)) { /* not a forwarding BBS */
- sprintf(sigwork,"%s/%s.sig",Signature,
- m->tofrom ? m->tofrom : m->name);
- if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE){
- while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
- fputs(sigwork,m->tfile);
- fclose(fp);
- }
- }
-
- if((host = strrchr(m->to,'@')) == NULLCHAR) {
- host = Hostname; /* use our hostname */
- if(m->origto != NULLCHAR) {
- /* rewrite_address() will be called again by our
- * SMTP server, so revert to the original address.
- */
- xfree(m->to);
- m->to = m->origto;
- m->origto = NULLCHAR;
- }
- }
- else
- host++; /* use the host part of address */
-
- /* make up full from name for work file */
- if(m->tofrom != NULLCHAR)
- sprintf(fullfrom,"%s%%%s.bbs@%s",m->tofrom, m->name, Hostname);
- else
- sprintf(fullfrom,"%s@%s",m->name,Hostname);
- if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
- fseek(m->tfile,0L,0); /* reset to beginning */
- fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
- del_list(cclist);
- cclist = NULLLIST;
- }
- addlist(&cclist,m->to,0);
- fseek(m->tfile,0L,0);
- fail += queuejob(m->tfile,host,cclist,fullfrom);
- del_list(cclist);
- fclose(m->tfile);
- if(fail)
- usputs(m->user,(m->sid & MBX_SID) ?
- "*** NO\n" : "%sCouldn't queue message for delivery\n");
- else
- if(m->tomsgid != NULLCHAR &&
- (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
- fprintf(fp,"%s\n",m->tomsgid); /* Save BID in history file */
- fclose(fp);
- }
- if(m->sid & MBX_SID)
- smtptick(NULL); /* wake SMTP to send that mail */
- return 0;
- }
-
- static int
- dosid(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *)p;
- char *sid_features;
-
- if(argc == 1)
- return 1;
-
- if(argv[1][strlen(argv[1]) - 1] != ']') /* must be an SID */
- return 1;
-
- m->sid = MBX_SID;
- /* Now check to see if this is an RLI board.
- * As usual, Hank does it a bit differently from
- * the rest of the world.
- */
- if(m->stype == 'R' && strncmp(argv[1],"li",2) == 0)/* [RLI] at a minimum */
- m->sid |= MBX_RLI_SID;
- /* Check to see if the BBS supports a kludge called "hierarchical
- * routing designators."
- */
- sid_features = strrchr(argv[1],'-');
-
- if((sid_features != NULLCHAR) &&
- (strlen(sid_features) > 3) &&
- (strchr(sid_features,'h') != NULLCHAR) &&
- (strchr(sid_features,'$') != NULLCHAR))
- /*
- if(strlen(argv[1]) > 2 && strcmp(argv[1]+strlen(argv[1])-3,"h$]") == 0)
- */
- m->sid |= MBX_HIER_SID;
- return 0;
- }
-
- #ifdef XXX
- /* Show non-private routes only */
- int
- dombiproute(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int i,bits;
- struct route *rp;
- struct mbx *m = (struct mbx *)p;
- char buf[85];
-
- if(m->privs & NO_LISTS) {
- tputs(Noperm);
- return 0;
- }
-
- tputs(RouteHeader);
- for(bits = 31; bits >= 0; bits--) {
- for(i = 0; i < HASHMOD; i++) {
- for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
- if(dumproute(rp,buf) == EOF)
- return 0;
-
- }
- }
- }
- if(R_default.iface != NULLIF)
- dumproute(&R_default,buf);
- return 0;
- }
- #endif
-
- #ifdef AX25
- static int
- dombroute(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct axroute_tab *rp;
- int i, k;
- char tmp[11];
- struct ax25_addr call;
-
- struct mbx *m = (struct mbx *)p;
-
- if( argc < 2) {
- usputs(m->user,"Destinations:\n");
-
- for(i = 0, k = 0; i < AXROUTESIZE; i++) {
- for (rp = axroute_tab[i]; rp; rp = rp->next) {
- pax25(tmp,(char *) &rp->call);
- if(strlen(tmp) > 1) {
- usprintf(m->user,"%-11.11s%s",tmp,(k == 6) ? "\n" : "");
- k = (k+1) % 7;
- }
- }
- }
- if (i)
- usputs(m->user,"\n");
- return 0;
- }
- for (i = 1; i < argc; i++)
- if (setcall((char *) &call,argv[i]) || (rp = axroute_tabptr(&call,0)) == 0)
- usprintf(m->user,"No route to %s\n",pax25(tmp,(char *) &call));
- else {
- tputs(" Date GMT Interface Path\n");
- doroutelistentry(rp);
- }
- return 0;
- }
- #endif
-
- static int
- dombstat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- dostatus(9,0,p);
- return;
- }
-
- static int
- dombescape(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *)p;
-
- if(argc < 2){
- usputs(m->user,"The escape character is: ");
- if(m->escape < 32)
- usprintf(m->user,"CTRL-%c\n",m->escape+'A'-1);
- else
- usprintf(m->user,"'%c'\n",m->escape);
- return 0;
- }
- if(strlen(argv[1]) > 1)
- if(isdigit(*argv[1]))
- m->escape = (char) atoi(argv[1]);
- else
- return 1;
- else
- m->escape = *argv[1];
- return 0;
- }
-
- static int
- dodownload(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *fp;
- struct mbx *m = (struct mbx *)p;
- char *file = pathname(m->path,argv[1]);
-
- if(!permcheck(m->path,m->privs,RETR_CMD,file)) {
- xfree(file);
- return -3;
- } else {
- if((fp = open_file(file,READ_TEXT,m->user,0)) != NULLFILE) {
- logmb(m->user,"download %c %s",m->stype,file);
- if(m->stype == 'U'){ /* uuencode ? */
- fclose(fp);
- fp = fopen(file,READ_BINARY); /* assume non-ascii */
- uuencode(fp,m->user,argv[1]);
- } else
- sendfile(fp,m->user,ASCII_TYPE,0);
- fclose(fp);
- }
- }
- xfree(file);
- return 0;
- }
-
- static int
- dombuser(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int i, len, s;
- char *cp, *cp1, fsocket[MAXSOCKSIZE], upl[40], down[40];
- struct usock *up, *up1;
-
- #ifdef AX25
- char tmp[AXBUF];
- #endif
-
- #ifdef NETROM
- struct nrroute_tab *np;
- char temp[AXBUF], *cp2, *cp3;
- char circuit[] = "Circuit (%s%s %s)";
- #endif
-
- struct mbx *m = (struct mbx *) p;
-
- tprintf("%sUser:\n",(m->family == AF_NETROM) ? mbnrid : "");
-
- for(i = 0; i < NUMMBX; i++) {
- if((m = Mbox[i]) != NULLMBX){
- len = MAXSOCKSIZE;
- getpeername(m->user,fsocket,&len);
- cp = strxdup(psocket(fsocket));
-
- upl[0] = '\0';
- down[0] = '\0';
-
- switch(m->family) { /* UPLINK */
- #ifdef AX25
- case AF_AX25:
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(upl,"Uplink (%s)",cp);
- break;
- #endif
- #ifdef NETROM
- case AF_NETROM:
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- *cp1 = '\0';
- cp1 += 3;
- setcall(temp,cp1);
- if((np = find_nrroute(temp)) != NULLNRRTAB)
- cp2 = strxdup(np->alias);
- else
- cp2 = "";
- if((cp3 = strchr(cp2,' ')) != NULLCHAR)
- *cp3 = '\0';
- if(isalnum(*cp2))
- strcat(cp2,":");
- else
- *cp2 = '\0';
- sprintf(upl,circuit,cp2,cp1,cp);
- xfree(cp2);
- break;
- #endif
- case AF_INET:
- if((cp1 = strchr(cp,':')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(upl,"Telnet (%s)",cp);
- break;
- default:
- strcpy(upl,"Connect");
- break;
- }
- xfree(cp);
- tprintf("%-36s",upl);
-
- for(s = SOCKBASE; s < Nusock + SOCKBASE; s++) {
- if((up = itop(s)) == NULLUSOCK || s == m->user)
- continue;
- up1 = itop(m->user);
- if(up->owner == up1->owner) {
- getpeername(s,fsocket,&len);
- cp = strxdup(psocket(fsocket));
- switch(up->type) {
- case TYPE_TCP:
- if((cp1 = strchr(cp,':')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(down,"Telnet (%s)",cp);
- break;
- #ifdef AX25
- case TYPE_AX25I:
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(down,"Downlink (%s %s)",
- pax25(tmp,m->nodename),cp);
- break;
- #endif
- #ifdef NETROM
- case TYPE_NETROML4:
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- *cp1 = '\0';
- cp1 += 3;
- setcall(temp,cp1);
- np = find_nrroute(temp);
- cp2 = strxdup(np->alias);
- if((cp3 = strchr(cp2,' ')) != NULLCHAR)
- *cp3 = '\0';
- addrcp(cp,m->nodename);
- cp[ALEN] ^= 0x1e;
- if(isalnum(*cp2))
- strcat(cp2,":");
- else
- *cp2 = '\0';
- sprintf(down,circuit,cp2,cp1,pax25(temp,cp));
- xfree(cp2);
- break;
- #endif
- default:
- strcpy(down,"Connect");
- break;
- }
- xfree(cp);
- tprintf("<--> %s",down);
- break;
- }
- }
- tputs("\n");
- }
- }
- return 0;
- }
-
- static int
- dombupload(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *fp;
- char buf[LINELEN];
- struct mbx *m = (struct mbx *)p;
- char *file = pathname(m->path,argv[1]);
-
- if(!permcheck(m->path,m->privs,STOR_CMD,file)) {
- xfree(file);
- return -3;
- }
- if((fp = open_file(file,WRITE_TEXT,m->user,1)) == NULLFILE) {
- xfree(file);
- return 0;
- }
- usprintf(m->user,"Send file. %s",Howtoend);
- logmb(m->user,"upload %s",file);
- for(;;){
- if(mbxrecvline(m->user,buf,LINELEN,-1) == -1){
- unlink(file);
- break;
- }
- if(buf[0] == 0x01){ /* CTRL-A */
- unlink(file);
- usputs(m->user,Aborted);
- break;
- }
- if(buf[0] == CTLZ
- || !stricmp(buf,"/ex")
- || !stricmp(buf,"***end")
- || !stricmp(buf,"."))
- break;
- fputs(buf,fp);
-
- #if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
- /* Needed only if the OS uses a CR/LF
- * convention oand putc doesn't do
- * an automatic translation
- */
- if(putc('\r',fp) == EOF)
- break;
- #endif
- if(putc('\n',fp) == EOF)
- break;
- }
- fclose(fp);
- return 0;
- }
-
- static int
- dowhat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *fp;
- char *file;
-
- struct mbx *m = (struct mbx *)p;
-
- if(m->security)
- return 0;
-
- if(argc < 2)
- file = strxdup(m->path);
- else
- file = pathname(m->path,argv[1]);
-
- if(!permcheck(m->path,m->privs,RETR_CMD,file)) {
- xfree(file);
- return -3;
- }
-
- if((fp = dir(file,1)) != NULLFILE)
- sendfile(fp,m->user,ASCII_TYPE,0);
- fclose(fp);
- xfree(file);
- return 0;
- }
-
- int
- dosysopset(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(strlen(argv[1]) == 5 && atol(argv[1]) != 0)
- strcpy(number,argv[1]);
- return 0;
- }
- int
- dormncsys(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- long org;
-
- long n1, n2, x;
- int i;
-
- org=atol(number); // eigene Nr
-
- n1 = atol(argv[1]); // Fremde Nr
- if (argc < 3)
- n2 = org;
- else
- n2 = atol(argv[2]);
-
- for (i = 0, x = 0; i < 5; i++) {
- x += (n1 % 10) * (n2 % 10);
- n1 /= 10;
- n2 /= 10;
- }
-
- printf("%d\n",x);
- return 0;
-
- }
-
-
-
- static int
- dosysop(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int c, i, k;
- unsigned long int digit1[25], digit;
- extern struct cmds Cmds[];
-
- struct mbx *m = (struct mbx *) p;
-
- logmb(m->user,"SYSOP");
- if(!(m->privs & SYSOP_CMD))
- return -3;
-
- randomize();
- for(i=0; i<15; i++) {
- digit1[i] = random(10);
- usprintf(m->user,"%d",digit1[i]);
-
- if(i == 4 || i == 9)
- usputs(m->user,", ");
- }
- usputs(m->user,">");
-
- c = mbxrecvline(m->user,m->line,MBXLINE,m->escape);
- if(c == EOF || c == -2)
- return 0;
-
- if((digit = atol(number)) == 0)
- digit = 22222;
- digit1[15] = digit/10000;
- digit -= digit1[15]*10000;
- digit1[16] = digit/1000;
- digit -= digit1[16]*1000;
- digit1[17] = digit/100;
- digit -= digit1[17]*100;
- digit1[18] = digit/10;
- digit -= digit1[18]*10;
- digit1[19] = digit;
-
- for(i=0; i<3; i++) {
- digit1[i+20] = 0;
- for(k=0; k<5; k++)
- digit1[i+20] += digit1[k+i*5] * digit1[k+15];
- }
- rip(m->line);
-
- if((digit = atol(m->line)) != 0
- && (digit == digit1[20] || digit == digit1[21] || digit == digit1[22])) {
- for(;;) {
- usputs(m->user,"Net> ");
- c = mbxrecvline(m->user,m->line,MBXLINE,m->escape);
- if(c == EOF || c == -2)
- break;
- cmdparse(Cmds,m->line,NULL);
- }
- return 0;
- } else
- return -3;
- }
-
- /* Handle the "*** Done" command when reverse forwarding ends
- */
- static int
- dostars(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *)p;
-
- if(strcmp(argv[1],"error?") == 0)
- return -2;
- if(strcmp(argv[1],"done") == 0 && (m->sid & MBX_SID)) /* "*** Done" or similar */
- return 2;
- return -1;
- }
-
- static int
- doarea(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *fp;
- char *cp, *area, Areatext[] = "Area %s: %d message%s\n";
- static char Nomail[] = "No message%s\n";
-
- struct mbx *m = (struct mbx *) p;
-
- if(argc < 2){
- area = strxdup(m->area);
- while((cp = strchr(area,'/')) != NULLCHAR)
- *cp = '.';
- usprintf(m->user,"Current area: %s\nAvailable areas:\n",area);
- xfree(area);
- usprintf(m->user,"%-15s Your private mail area\n",m->name);
- if((fp = fopen(Arealist,READ_TEXT)) != NULLFILE) {
- sendfile(fp,m->user,ASCII_TYPE,0);
- fclose(fp);
- usputs(m->user,"\n");
- }
- return 0;
- }
- if((m->privs & SYSOP_CMD) || strcmp(m->name,argv[1]) == 0){
- changearea(m,argv[1]);
- if(!strcmp(m->name,m->area)) {
- if(m->nmsgs) {
- usprintf(m->user,"You have %d message%s",
- m->nmsgs,m->nmsgs == 1 ? "" : "s");
- if(m->newmsgs)
- usprintf(m->user," - %d new",m->newmsgs);
- usputs(m->user,"\n\n");
- } else {
- m->narea[0] = '\0';
- }
- } else {
- area = strxdup(m->area);
- while((cp = strchr(area,'/')) != NULLCHAR)
- *cp = '.';
- usprintf(m->user,Areatext,area,m->nmsgs,m->nmsgs == 1 ? "" : "s");
- xfree(area);
- }
- return 0;
- }
- if(isarea(argv[1])) {
- changearea(m,argv[1]);
- area = strxdup(m->area);
- while((cp = strchr(area,'/')) != NULLCHAR)
- *cp = '.';
- if(m->nmsgs)
- usprintf(m->user,Areatext,area,m->nmsgs,m->nmsgs == 1 ? "" : "s");
- else
- usprintf(m->user,Nomail,"s");
- xfree(area);
- }
- else
- usprintf(m->user,"No such area: %s\n",argv[1]);
- return 0;
- }
-
- /* subroutine to do the actual switch from one area to another */
- void
- changearea(m,area)
- struct mbx *m;
- char *area;
- {
- char *cp;
-
- semwait(&Areawait,1);
- closenotes(m);
- m->nmsgs = m->newmsgs = m->current = 0;
- strcpy(m->area,area);
- #ifdef MSDOS
- while((cp = strchr(m->area,'\\')) != NULLCHAR)
- *cp = '/';
- #endif
- strcpy(m->narea,m->area);
- if((cp = strpbrk(m->narea," -/.:")) != NULLCHAR)
- *cp = '\0';
- strupr(m->narea);
- scanmail(m);
- semrel(&Areawait);
- }
-
- #ifdef AX25
- static int
- dogateway(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *)p;
- struct sockaddr_ax fsocket, lsocket;
- int s;
- char *ap, path[10*AXALEN+1];
- struct iface *ifp = NULLIF;
- struct ax25_cb axp;
-
- if(argc < 2) {
- if(MAttended){
- char buf[5], *newargv[3];
-
- newargv[0] = "telnet";
- newargv[1] = (MHostname != NULLCHAR) ? MHostname : Hostname;
- sprintf(buf,"%d",IPPORT_TTYLINK);
- newargv[2] = buf;
- return dombtelnet(3,newargv,p);
- } else {
- char *name = strxdup(MBHostname);
- strlwr(name);
- usprintf(m->user,"OP is absent, pse leave msg with \"s %s\"\n",name);
- xfree(name);
- return 0;
- }
- }
-
- if(!(m->privs & AX25_CMD))
- return -3;
-
- argc--;
- argv++;
-
- if((ifp = if_lookup(*argv)) != NULLIF) {
- if(ifp->output != ax_output) {
- usprintf(m->user,Badax,*argv);
- return 0;
- }
- argc--;
- argv++;
- }
- for (ap = path; argc > 0; argc--, argv++) {
- if (!strncmp("via", *argv, strlen(*argv))) continue;
- if (ap > path + sizeof(path) - 1) {
- usputs(m->user,"Max 8 digis\n");
- return 0;
- }
- if (setcall(ap, *argv)) {
- usprintf(m->user,"Invalid call %s\n", *argv);
- return 0;
- }
- ap[ALEN] &= ~E;
-
- if (ap == path) {
- ap += AXALEN;
- addrcp(ap,Mycall);
- ap[ALEN] &= ~E;
- }
- ap += AXALEN;
- }
- if (ap < path + 2 * AXALEN) {
- usputs(m->user,"Missing call\n");
- return 0;
- }
- ap[-1] |= E;
-
- memset(&axp,0,sizeof(struct ax25_cb));
-
- build_path(&axp,ifp,path,0,0);
-
- if(!axp.iface) {
- usputs(m->user,"No specified iface\n");
- return 0;
- }
-
- addrcp(axp.path + AXALEN,axp.iface->hwaddr);
- axroute_add(&axp,0);
-
- if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
- usputs(m->user,Nosocket);
- return 0;
- }
-
- fsocket.sax_family = AF_AX25;
- addrcp(fsocket.ax25_addr,axp.path);
- memcpy(fsocket.iface,axp.iface->name,ILEN);
- m->startmsg = NULLCHAR;
-
- lsocket.sax_family = AF_AX25;
- addrcp(lsocket.ax25_addr,(*m->name == '\0') ?
- axp.iface->hwaddr : m->nodename);
- bind(s,(char *)&lsocket,sizeof(struct sockaddr_ax));
- return gw_connect(m,s,(char *)&fsocket, sizeof(struct sockaddr_ax));
- }
- #else
- static int
- dogateway(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2) {
- if(MAttended){
- char buf[5], *newargv[3];
-
- newargv[0] = "telnet";
- newargv[1] = Hostname;
- sprintf(buf,"%d",IPPORT_TTYLINK);
- newargv[2] = buf;
- return dombtelnet(3,newargv,p);
- } else {
- char *name;
-
- name = strxdup(MBHostname);
- strlwr(name);
- usprintf(m->user,"OP is absent, pse leave msg with \"s %s\"\n",name);
- xfree(name);
- return 0;
- }
- }
-
- usputs(m->user,Noserv);
- return 0;
- }
- #endif
-
- static int
- dombtelnet(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s, len, i;
- char dsocket[MAXSOCKSIZE];
- struct sockaddr_in fsocket;
-
- struct mbx *m = (struct mbx *) p;
-
- fsocket.sin_family = AF_INET;
- fsocket.sin_port = (argc < 3) ? IPPORT_TELNET : atoi(argv[2]);
-
- if((fsocket.sin_addr.s_addr = resolve(argv[1])) == 0){
- usprintf(m->user,Badhost,argv[1]);
- return 0;
- }
- /* Only local telnets are are allowed to the unprivileged user */
- if(!(m->privs & TELNET_CMD) && !ismyaddr(fsocket.sin_addr.s_addr))
- return -3;
-
- if((s = socket(AF_INET,SOCK_STREAM,0)) == -1){
- usputs(m->user,Nosocket);
- return 0;
- }
- switch(fsocket.sin_port) {
- case IPPORT_TTYLINK:
- m->startmsg = mxallocw(80);
- len = MAXSOCKSIZE;
- i = getpeername(m->user,dsocket,&len);
- sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
- m->name,(i != -1) ? psocket(dsocket): Hostname);
- break;
- #ifdef CONVERS
- case IPPORT_CONVERS:
- if(m->startmsg == NULLCHAR) {
- m->startmsg = mxallocw(40);
- sprintf(m->startmsg,
- "/n %s %d\n",m->name,(argc > 3) ? atoi(argv[3]) : 0);
- }
- m->state = MBX_CONVERS;
- break;
- #endif
- }
- return gw_connect(m,s,(char *)&fsocket,SOCKSIZE);
- }
-
- static int
- dombfinger(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *)p;
- char *host, *user = NULLCHAR, buf[8], *newargv[3];
-
- if(argc > 2){
- usputs(m->user,"Usage: finger <user[@host]|@host>\n");
- return 0;
- }
- host = Hostname;
- if(argc == 2){
- if((host = strchr(argv[1], '@')) != NULLCHAR){
- *host = '\0';
- host++;
- } else
- host = Hostname;
- user = argv[1];
- }
- m->startmsg = mxallocw(80);
- sprintf(m->startmsg,"%s\n",(user != NULLCHAR) ? user : "");
- newargv[0] = "telnet";
- newargv[1] = host;
- sprintf(buf,"%d",IPPORT_FINGER);
- newargv[2] = buf;
- return dombtelnet(3,newargv,p);
- }
-
- #ifdef CONVERS
- static int
- dombconvers(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[8], *newargv[3];
-
- struct mbx *m = (struct mbx *) p;
-
- m->startmsg = mxallocw(40);
- sprintf(m->startmsg,"/n %s %s\n",m->name,(argc > 1) ? argv[1] : "0");
- newargv[0] = "telnet";
- newargv[1] = Hostname;
- sprintf(buf,"%d",IPPORT_CONVERS);
- newargv[2] = buf;
- return dombtelnet(3,newargv,p);
- }
- #endif
-
- /* Generic mbox gateway code. It sends and frees the contents of m->startmsg
- * when the connection has been established unless it a null pointer.
- */
- static int near
- gw_connect(m,s,fsocket,len)
- struct mbx *m;
- int s;
- char *fsocket;
- int len;
- {
- int c;
- char *cp, *cp1, *node, buf[80];
- struct proc *child;
- struct gwalarm *gwa;
-
- sockmode(s,SOCK_ASCII);
- child = newproc("gw supervisor",256,gw_superv,0,Curproc,m,0);
- if(m->family == AF_AX25) {
- usputs(m->user,"link setup...\n");
- usflush(m->user);
- }
- node = strxdup(psocket((struct sockaddr *)fsocket));
- if((cp1 = strchr(node,' ')) != NULLCHAR)
- *cp1 = '\0';
-
- if(connect(s,fsocket,len) == -1){
- if((cp = sockerr(s)) != NULLCHAR) {
- switch(cp[0]) {
- case 'R':
- sprintf(buf,"%susy from",
- (m->family == AF_NETROM)?"B":"*** b");
- break;
- case 'T':
- if(m->family != AF_NETROM) {
- sprintf(buf,"*** timeout with");
- break;
- }
- default:
- sprintf(buf,"%sailure with",
- (m->family == AF_NETROM)?"F":"*** f");
- break;
- }
- usprintf(m->user,"%s%s %s\n",
- (m->family == AF_NETROM) ? mbnrid : "",buf,node);
- }
- xfree(m->startmsg);
- m->startmsg = NULLCHAR;
- xfree(node);
- killproc(child);
- close_s(s);
- return 0;
- }
- logmb(Curproc->input,"connect %s",node);
- usprintf(m->user,"%s%sonnected to %s\n",
- (m->family == AF_NETROM) ? mbnrid : "",
- (m->family == AF_NETROM) ? "C" : "*** c",
- node);
- xfree(node);
- /* The user did not type the escape character */
- killproc(child);
-
- if(m->startmsg != NULLCHAR){
- usputs(s,m->startmsg);
- xfree(m->startmsg);
- m->startmsg = NULLCHAR;
- }
-
- /* Since NOS does not flush the output socket after a certain
- * period of time, we have to arrange that ourselves.
- */
- gwa = (struct gwalarm *)mxallocw(sizeof(struct gwalarm));
- stop_timer(&gwa->t);
- gwa->s1 = Curproc->output;
- gwa->s2 = s;
- gwa->t.func = gw_alarm;
- gwa->t.arg = (void *) gwa;
- set_timer(&gwa->t,240); /* DB3FL */
- start_timer(&gwa->t);
- /* Fork off the receive process */
- child = newproc("gw in",1024,gw_input,s,m,Curproc,0);
-
- for(;;){
- if((c = recvchar(Curproc->input)) == EOF)
- break;
- if(c == m->escape){
- if(socklen(Curproc->input,0))
- recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
- break;
- }
- if(usputc(s,c) == EOF)
- break;
- }
- stop_timer(&gwa->t);
- xfree((char *)gwa);
- close_s(s);
- killproc(child); /* get rid of the receive process */
- if(m->family == AF_INET || m->family == AF_LOCAL)
- usprintf(m->user,"%c%c%c\n",IAC,WONT,TN_ECHO);
- return 0;
- }
-
- static void
- gw_input(s,notused,p)
- int s;
- void *notused;
- void *p;
- {
- int c;
- char *cp;
-
- struct proc *parent = (struct proc *) p;
- struct mbx *m = (struct mbx *) notused;
-
- while((c = recvchar(s)) != EOF)
- tputc(c);
- if((cp = sockerr(s)) != NULLCHAR && m->family != AF_NETROM) {
- switch(*cp) {
- case 'T':
- usprintf(m->user,"\n*** %s: Link failure",MBHostname);
- break;
- case 'R':
- usputs(m->user,"*** DM received");
- break;
- }
- }
- usprintf(m->user,"\n%s%seconnected to %s\n",
- (m->family == AF_NETROM) ? mbnrid : "",
- (m->family == AF_NETROM) ? "R" : "*** r",
- MBHostname);
-
- /* Tell the parent that we are no longer connected */
- alert(parent,(void *)ENOTCONN);
- pwait(Curproc); /* Now wait to be killed */
- }
-
- /* Check if the escape character is typed while the parent process is busy
- * doing other things.
- */
- static void
- gw_superv(null,proc,p)
- int null;
- void *proc;
- void *p;
- {
- int c;
- struct proc *parent = (struct proc *) proc;
- struct mbx *m = (struct mbx *) p;
-
- while((c = recvchar(Curproc->input)) != EOF)
- if(c == m->escape){
- /* flush anything in the input queue */
- if(socklen(Curproc->input,0))
- recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
- break;
- }
- alert(parent,(void *)EINTR); /* Tell the parent to quit */
- pwait(Curproc); /* Please kill me */
- }
-
- static void
- gw_alarm(p)
- void *p;
- {
- struct gwalarm *gwa = (struct gwalarm *)p;
- char oldbl;
- struct usock *up;
-
- /* Flush sockets s1 and s2, but first make sure that the socket
- * is set to non-blocking mode, to prevent the flush from blocking
- * if the high water mark has been reached.
- */
- if((up = itop(gwa->s1)) != NULLUSOCK) {
- oldbl = up->noblock;
- up->noblock = 1;
- usflush(gwa->s1);
- up->noblock = oldbl;
- }
- if((up = itop(gwa->s2)) != NULLUSOCK) {
- oldbl = up->noblock;
- up->noblock = 1;
- usflush(gwa->s2);
- up->noblock = oldbl;
- }
- start_timer(&gwa->t);
- }
-
- #ifdef AX25
- static int
- dombheard(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return doaxheard(argc,argv,p);
- }
- #endif
-
- #ifdef NETROM
- static int
- dombnodes(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m = (struct mbx *) p;
-
- if(!(m->privs & NETROM_CMD))
- return -3;
-
- if(Nrifaces[0].alias == NULLCHAR) {
- usputs(m->user,Noserv);
- return 0;
- }
- if(argc < 2 || (argc > 1 && stricmp(argv[1],"tcp") == 0)) {
- usprintf(m->user,"%sNodes:\n",(m->family == AF_NETROM) ? mbnrid : "");
- return doroutedump(argc < 2 ? 9 : 0,0,p);
- }
- if(dorouteinfo(9,argv,p) == -1) {
- usprintf(m->user,"%s%so route to %s\n",
- (m->family == AF_NETROM) ? mbnrid : "",
- (m->family == AF_NETROM) ? "N" : "*** n",
- strupr(argv[1]));
- return -1;
- }
- return 0;
- }
-
- static int
- dombnrconnect(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s;
- struct sockaddr_nr lsocket, fsocket;
- char *np, alias[AXBUF];
-
- struct mbx *m = (struct mbx *) p;
-
- if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
- usputs(m->user,Nosocket);
- return 0;
- }
- lsocket.nr_family = AF_NETROM;
-
- /* Set up our local username, bind would use Mycall instead */
- addrcp(lsocket.nr_addr.user,m->nodename);
- lsocket.nr_addr.user[ALEN] ^= 0x1e;
-
- /* Putting anything else than Mycall here will not work */
- addrcp(lsocket.nr_addr.node,Mycall);
- bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
-
- /* See if the requested destination could be an alias, and
- * find and use it if it is. Otherwise assume it is an ax.25
- * address.
- */
- if(putalias(alias,argv[1],0) != -1 &&
- (np = find_nralias(alias)) != NULLCHAR){
- addrcp(fsocket.nr_addr.user,np);
- addrcp(fsocket.nr_addr.node,np);
- } else { /* parse ax25 callsign */
- /* Only the user callsign of the remote station is never used by */
- /* NET/ROM, but it is needed for the psocket() call. */
- setcall(fsocket.nr_addr.user,argv[1]);
- setcall(fsocket.nr_addr.node,argv[1]);
- }
- fsocket.nr_family = AF_NETROM;
- return gw_connect(m,s,(char *)&fsocket, sizeof(struct sockaddr_nr));
- }
- #endif
-
- /* States for send line parser state machine */
- #define LOOK_FOR_USER 2
- #define IN_USER 3
- #define AFTER_USER 4
- #define LOOK_FOR_HOST 5
- #define IN_HOST 6
- #define AFTER_HOST 7
- #define LOOK_FOR_FROM 8
- #define IN_FROM 9
- #define AFTER_FROM 10
- #define LOOK_FOR_MSGID 11
- #define IN_MSGID 12
- #define FINAL_STATE 13
- #define ERROR_STATE 14
-
- /* Prepare the addressee. If the address is bad, return -1, otherwise
- * return 0
- */
- static int near
- mbx_to(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *cp, *user, *host, *from, *msgid;
- int state, i, userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
-
- struct mbx *m = (struct mbx *)p;
-
- /* Free anything that might be allocated
- * since the last call to mbx_to() or mbx_reply()
- */
- xfree(m->to);
- m->to = NULLCHAR;
- xfree(m->tofrom);
- m->tofrom = NULLCHAR;
- xfree(m->tomsgid);
- m->tomsgid = NULLCHAR;
- xfree(m->origto);
- m->origto = NULLCHAR;
-
- if(argc == 1)
- return -1;
- i = 1;
- cp = argv[i];
- state = LOOK_FOR_USER;
- while(state < FINAL_STATE){
- switch(state){
- case LOOK_FOR_USER:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE; /* no user */
- } else {
- user = cp; /* point at start */
- userlen++; /* start counting */
- state = IN_USER;
- }
- break;
- case IN_USER:
- switch(*cp){
- case '\0':
- state = AFTER_USER; /* done with username */
- break;
- case '@':
- state = LOOK_FOR_HOST; /* hostname should follow */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* from name should follow */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id should follow */
- break;
- default:
- userlen++; /* part of username */
- }
- break;
- case AFTER_USER:
- switch(*cp){
- case '@':
- state = LOOK_FOR_HOST; /* hostname follows */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- state = ERROR_STATE;
- }
- break;
- case LOOK_FOR_HOST:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE;
- break;
- }
- if(*cp == '\0')
- break;
- host = cp;
- hostlen++;
- state = IN_HOST;
- break;
- case IN_HOST:
- switch(*cp){
- case '\0':
- state = AFTER_HOST; /* found user@host */
- break;
- case '@':
- state = ERROR_STATE; /* user@host@? */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- hostlen++;
- }
- break;
- case AFTER_HOST:
- switch(*cp){
- case '@':
- state = ERROR_STATE; /* user@host @ */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* user@host < */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host $ */
- break;
- default:
- state = ERROR_STATE; /* user@host foo */
- }
- break;
- case LOOK_FOR_FROM:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE;
- break;
- }
- if(*cp == '\0')
- break;
- from = cp;
- fromlen++;
- state = IN_FROM;
- break;
- case IN_FROM:
- switch(*cp){
- case '\0':
- state = AFTER_FROM; /* user@host <foo */
- break;
- case '<':
- state = ERROR_STATE; /* user@host <foo< */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- fromlen++;
- }
- break;
- case AFTER_FROM:
- switch(*cp){
- case '@': /* user@host <foo @ */
- case '<': /* user@host <foo < */
- state = ERROR_STATE;
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host <foo $ */
- break;
- default:
- state = ERROR_STATE; /* user@host foo */
- }
- break;
- case LOOK_FOR_MSGID:
- if(*cp == '\0')
- break;
- msgid = cp;
- msgidlen++;
- state = IN_MSGID;
- break;
- case IN_MSGID:
- if(*cp == '\0')
- state = FINAL_STATE;
- else
- msgidlen++;
- break;
- default:
- /* what are we doing in this state? */
- state = ERROR_STATE;
- }
- if(*(cp) == '\0'){
- ++i;
- if(i < argc)
- cp = argv[i];
- else
- break;
- } else
- ++cp;
- }
- if(state == ERROR_STATE || state == LOOK_FOR_HOST
- || state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
- return -1; /* syntax error */
-
- m->to = mxallocw(userlen + hostlen + 2);
-
- strncpy(m->to, user, userlen);
- m->to[userlen] = '\0';
-
- if(hostlen){
- m->to[userlen] = '@';
- strncpy(m->to + userlen + 1, host, hostlen);
- m->to[userlen + hostlen + 1] = '\0';
- }
- if(fromlen){
- m->tofrom = mxallocw(fromlen + 1);
- strncpy(m->tofrom, from, fromlen);
- m->tofrom[fromlen] = '\0';
- }
- if(msgidlen){
- m->tomsgid = mxallocw(msgidlen + 1);
- strncpy(m->tomsgid, msgid, msgidlen);
- m->tomsgid[msgidlen] = '\0';
- }
- return 0;
- }
-
- /* This opens the data file and writes the mail header into it.
- * Returns 0 if OK, and -1 if not.
- */
- static int near
- mbx_data(m,cclist,extra)
- struct mbx *m;
- struct list *cclist; /* list of carbon copy recipients */
- char *extra; /* optional extra header lines */
- {
- struct list *ap;
- int cccnt = 0;
-
- if((m->tfile = temp_file(0,1)) == NULLFILE)
- return -1;
- fprintf(m->tfile,Hdrs[RECEIVED]);
- if(m->tofrom != NULLCHAR)
- fprintf(m->tfile,"from %s.bbs ",m->name);
- fprintf(m->tfile,"by %s (%s)\n\tid AA%ld; %s",
- Hostname, Version, get_msgid(), ptime(&currtime));
- fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&currtime));
- fprintf(m->tfile,Hdrs[MSGID]);
- if(m->tomsgid)
- fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name);
- else
- fprintf(m->tfile,"<%ld@%s>\n",get_msgid(), Hostname);
- fprintf(m->tfile,Hdrs[FROM]);
- if(m->tofrom)
- fprintf(m->tfile,"%s%%%s.bbs@%s\n",m->tofrom, m->name, Hostname);
- else
- fprintf(m->tfile,"%s@%s\n", m->name, Hostname);
- fprintf(m->tfile,"%s%s\n",Hdrs[TO],m->origto != NULLCHAR ? m->origto : m->to);
- /* Write Cc: line */
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- if(cccnt == 0){
- fprintf(m->tfile,"%s",Hdrs[CC]);
- cccnt = 4;
- }
- else {
- fprintf(m->tfile,", ");
- cccnt += 2;
- }
- if(cccnt + strlen(ap->val) > 80 - 3) {
- fprintf(m->tfile,"\n ");
- cccnt = 4;
- }
- fputs(ap->val,m->tfile);
- cccnt += strlen(ap->val);
- }
- if(cccnt)
- fputc('\n',m->tfile);
- fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->line);
- if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
- (m->sid & MBX_SID) !=0))
- fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
- if(extra != NULLCHAR)
- fprintf(m->tfile,extra);
- fputc('\n',m->tfile);
-
- return 0;
- }
-
- /* Returns true if string is in history file or if string appears to be a
- * message id generated by our system.
- */
- static int near
- msgidcheck(string)
- char *string;
- {
- FILE *fp;
- char buf[LINELEN], *cp;
-
- if(string == NULLCHAR)
- return 0;
- /* BID's that we have generated ourselves are not kept in the history
- * file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
- * our hostname, truncated so that the BID is no longer than 11
- * characters.
- */
- if((cp = strchr(string,'_')) != NULLCHAR && *(cp+1) != '\0' &&
- strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
- return 1;
-
- if((fp = fopen(Historyfile,READ_TEXT)) == NULLFILE)
- return 0;
- while(fgets(buf,LINELEN,fp) != NULLCHAR) {
- rip(buf);
- if(stricmp(string,buf) == 0) { /* found */
- fclose(fp);
- return 1;
- }
- }
- fclose(fp);
- return 0;
- }
-
- /* Read the rewrite file for lines where the first word is a regular
- * expression and the second word are rewriting rules. The special
- * character '$' followed by a digit denotes the string that matched
- * a '*' character. The '*' characters are numbered from 1 to 9.
- * Example: the line "*@*.* $2@$1.ampr.org" would rewrite the address
- * "foo@bar.xxx" to "bar@foo.ampr.org".
- * $H is replaced by our hostname, and $$ is an escaped $ character.
- * If the third word on the line has an 'r' character in it, the function
- * will recurse with the new address.
- */
- char *
- rewrite_address(addr)
- char *addr;
- {
- char *argv[10], buf[MBXLINE], *cp, *cp2, *retstr;
- int cnt;
- FILE *fp;
-
- if ((fp = fopen(Rewritefile,READ_TEXT)) == NULLFILE)
- return NULLCHAR;
- memset((char *)argv,0,10*sizeof(char *));
- while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
- if(*buf == '#') /* skip commented lines */
- continue;
- if((cp = strchr(buf,' ')) == NULLCHAR) /* get the first word */
- if((cp = strchr(buf,'\t')) == NULLCHAR)
- continue;
- *cp = '\0';
- if((cp2 = strchr(buf,'\t')) != NULLCHAR){
- *cp = ' ';
- cp = cp2;
- *cp = '\0';
- }
- if(!wildmat(addr,buf,argv))
- continue; /* no match */
- rip(++cp);
- cp2 = retstr = (char *)mxallocw(MBXLINE);
- while(*cp != '\0' && *cp != ' ' && *cp != '\t')
- if(*cp == '$') {
- if(isdigit(*(++cp)))
- if(argv[*cp - '0'-1] != '\0')
- strcat(cp2,argv[*cp - '0'-1]);
- if(*cp == 'h' || *cp == 'H') /* Our hostname */
- strcat(cp2,Hostname);
- if(*cp == '$') /* Escaped $ character */
- strcat(cp2,"$");
- cp2 = retstr + strlen(retstr);
- cp++;
- }
- else
- *cp2++ = *cp++;
- for(cnt=0; argv[cnt] != NULLCHAR; ++cnt)
- xfree(argv[cnt]);
- fclose(fp);
- /* If there remains an 'r' character on the line, repeat
- * everything by recursing.
- */
- if(strchr(cp,'r') != NULLCHAR || strchr(cp,'R') != NULLCHAR) {
- if((cp2 = rewrite_address(retstr)) != NULLCHAR) {
- xfree(retstr);
- return cp2;
- }
- }
- return retstr;
- }
- fclose(fp);
- return NULLCHAR;
- }
-
- /* uuencode a file -- translated from C++; both versions copyright 1990
- by David R. Evans, G4AMJ/NQ0I
- */
-
- static int near
- uuencode(infile,s,infilename)
- FILE *infile;
- int s; /* output socket */
- char *infilename;
- {
- int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
- unsigned long cnt = 0;
- unsigned char in[3], out[4], line[100];
- #ifdef UNIX
- struct stat stb;
-
- if(stat(infilename,&stb) != -1)
- mode = stb.st_mode & 0777; /* get real file protection mode */
- #endif
-
- usprintf(s,"\nbegin %03o %s\n", mode, infilename);
-
- /* do the encode */
- while ((in_chars = fread(in, 1, 3, infile)) != 0) {
- out[0] = in[0] >> 2;
- out[1] = in[0] << 6;
- out[1] = out[1] >> 2;
- out[1] = out[1] | (in[1] >> 4);
- out[2] = in[1] << 4;
- out[2] = out[2] >> 2;
- out[2] = out[2] | (in[2] >> 6);
- out[3] = in[2] << 2;
- out[3] = out[3] >> 2;
- for (n = 0; n < 4; n++)
- out[n] += ' ';
- n_read_so_far += in_chars;
- for (n = 0; n < 4; n++)
- line[n_written_so_far++] = out[n];
- if ((in_chars != 3) || (n_written_so_far == 60)) {
- line[(n_read_so_far + 2) / 3 * 4] = '\0';
-
- usprintf(s,"%c%s\n",n_read_so_far + ' ', line);
- usflush(s);
- cnt += n_read_so_far;
- n_read_so_far = 0;
- n_written_so_far = 0;
- }
- }
-
- if (usprintf(s," \nend\nsize %lu\n\n", cnt) == EOF)
- return 1;
- return 0;
- }
-
- /* Attempt to determine if this is third-pary mail. */
- static int
- thirdparty(m)
- struct mbx *m;
- {
- if(strpbrk(m->to,"@%!") != NULLCHAR)
- return 0;
-
- if(stricmp(m->to,MBHostname) == 0)
- return -1;
-
- if(stricmp(m->to,"sysop") == 0)
- return -1;
-
- return(isarea(m->to));
- }
-
- /* Subroutine for setting and displaying unsigned integer variables */
- int
- setuns(var,label,argc,argv)
- unsigned *var;
- char *label;
- int argc;
- char *argv[];
- {
- if(argc < 2)
- tprintf("%s: %u\n",label,*var);
- else
- *var = atoi(argv[1]);
-
- return 0;
- }
-
-
-